constant int X_SIZE = 1;
constant uint MIN = 0;
constant uint MAX = 25;

__kernel void PMrng(const uint seed_, const uint a_,
						const uint m_,const uint num_,__global uint *result){
	uint seed = seed_;
	uint a = a_;
	uint m = m_;
	uint min = MIN;
	uint max = MAX;
	size_t gid_x = get_global_id(0);
	size_t gid_y = get_global_id(1);
	uint num = num_;
	uint base_index = (gid_x + gid_y * X_SIZE) * num;
	
	for (int i = 0; i < num; i++){
		seed = (((ulong)seed* a) % m);
		result[base_index + i] = (seed % (max - min + 1) + min);
	}

}


__kernel void LCGrng(const uint seed_, const uint a_, const uint c_,
	const uint m_, const uint num_, __global uint *result){
	uint seed = seed_;
	uint a = a_;
	uint c = c_;
	uint m = m_;
	uint min = MIN;
	uint max = MAX;
	size_t gid_x = get_global_id(0);
	size_t gid_y = get_global_id(1);
	uint num = num_;
	uint base_index = (gid_x + gid_y * X_SIZE) * num;

	for (int i = 0; i < num; i++){
		seed = (a * seed + c) % m;
		result[base_index + i] = (seed % (max - min + 1) + min);
	}

}

__kernel void MTrng(const uint seed_, const uint num_, __global uint *result){
	uint seed = seed_;
	uint min = MIN;
	uint max = MAX;
	size_t gid_x = get_global_id(0);
	size_t gid_y = get_global_id(1);
	int index = 0;
	int MT[624];
	MT[0] = seed;
	uint num = num_;
	uint base_index = (gid_x + gid_y * X_SIZE) * num;
	for (int i = 1; i < 624; i++){
		MT[i] = 0xffffffff & (0x6c078965 * (MT[i - 1] ^ (MT[i - 1] >> 30)) + 1);
	}

	for (int i = 0; i < num; i++){
		if (index == 0){
			for (int i = 0; i < 624; i++){
				int y = (MT[i] & 0x80000000) + (MT[(i + 1) % 624] & 0x7fffffff);
				MT[i] = MT[(i + 397) % 624] ^ (y >> 1);
				if ((y % 2) != 0){
					MT[i] = MT[i] ^ (0x9908b0df);
				}
			}
		}

		int y = MT[index];
		y = y ^ (y >> 11);
		y = y ^ ((y << 7) & 0x9d2c5680);
		y = y ^ ((y << 15) & 0xefc60000);
		y = y ^ (y >> 18);

		index = (index + 1) % 624;
		result[base_index + i] = (y % (max - min + 1) + min);
	}
	

}


__kernel void XSrng(const uint seed ,const uint num_, __global uint *result){
	
	uint x = 123456789;
	uint y = 362436069;
	uint z = 521288629;
	uint w = seed;
	uint t = 0;
	uint min = MIN;
	uint max = MAX;
	size_t gid_x = get_global_id(0);
	size_t gid_y = get_global_id(1);
	uint num = num_;
	uint base_index = (gid_x + gid_y * X_SIZE) * num;

	for (int i = 0; i < num; i++){
		t = x ^ (x << 11);
		x = y; 
		y = z; 
		z = w;
		w = w ^ (w >> 19) ^ (t ^ (t >> 8));
		result[base_index + i] = (w % (max - min + 1) + min);
	}

}